/*!
    \file  link32fa016bx_sfc.h
    \brief definitions for the SFC

    \version 2024-04-12, V1.0.0, firmware for LINK32FA016BX
*/


#ifndef LINK32FA016BX_SFC_H
#define LINK32FA016BX_SFC_H

#include "link32fa016bx.h"

LINK32FA016BX_BEGIN_DECLS

/* SFC definitions */
#define SFC                        FMC_BASE

/* registers definitions */

/* SFC registers definitions */
#define SFC_CFG                       REG32(SFC + 0x00U)    /*!< SFC Config Register */
#define SFC_CMD                       REG32(SFC + 0x04U)    /*!< SFC Command Register */
#define SFC_CMD_ADDR                  REG32(SFC + 0x08U)    /*!< SFC Command Address Register */
#define SFC_CMD_DATA                  REG32(SFC + 0x0CU)    /*!< SFC Command Data Register */
#define SFC_CTRL                      REG32(SFC + 0x10U)    /*!< SFC Control Register */
#define SFC_STAT                      REG32(SFC + 0x14U)    /*!< SFC Status Register */
#define SFC_IE                        REG32(SFC + 0x18U)    /*!< SFC Interrupt Enable*/
#define SFC_IF                        REG32(SFC + 0x1CU)    /*!< SFC Interrupt Flag*/
#define SFC_FLOW_CFG                  REG32(SFC + 0x80U)    /*!< SFC Flow Control Config Register */
#define SFC_XTS_CFG                   REG32(SFC + 0x84U)    /*!< SFC XTS-AES Config Register */
#define SFC_XTS_TX_KEY                REG32(SFC + 0x88U)    /*!< SFC XTS-AES Text Key*/
#define SFC_XTS_TW_KEY                REG32(SFC + 0x8CU)    /*!< SFC XTS-AES Tweak Key */

#define SFC_CFG_SCK_DIV_PRE_Pos           16
#define SFC_CFG_SCK_DIV_PRE_Msk           BITS(16,23)
#define SFC_CFG_CSN_HOLD_TIMES_Pos        12
#define SFC_CFG_CSN_HOLD_TIMES_Msk        BITS(12,15)
#define SFC_CFG_CSN_SETUP_TIMES_Pos       8 
#define SFC_CFG_CSN_SETUP_TIMES_Msk       BITS(8,11)
#define SFC_CFG_SPI_IDLE_TIMES_Pos        4
#define SFC_CFG_SPI_IDLE_TIMES_Msk        BITS(4,7)
#define SFC_CFG_CPOL_CPHA_Pos             2
#define SFC_CFG_CPOL_CPHA_Msk             BITS(2,3)
#define SFC_CFG_BYTE_ORDER_Pos            1
#define SFC_CFG_BYTE_ORDER_Msk            BIT(1)
#define SFC_CFG_SFC_EN_Pos                0
#define SFC_CFG_SFC_EN_Msk                BIT(0)

#define SFC_CMD_FLASH_CMD_Pos             24
#define SFC_CMD_FLASH_CMD_Msk             BITS(24,31)
#define SFC_CMD_DUMMY_BYTES_Pos           20
#define SFC_CMD_DUMMY_BYTES_Msk           BITS(20,23)
#define SFC_CMD_ADDR_BYTES_Pos            16
#define SFC_CMD_ADDR_BYTES_Msk            BITS(16,19)
#define SFC_CMD_DATA_SPEED_Pos            14
#define SFC_CMD_DATA_SPEED_Msk            BITS(14,15)
#define SFC_CMD_DUMMY_SPEED_Pos           12
#define SFC_CMD_DUMMY_SPEED_Msk           BITS(12,13)
#define SFC_CMD_ADDR_SPEED_Pos            10
#define SFC_CMD_ADDR_SPEED_Msk            BITS(10,11)
#define SFC_CMD_CMD_SPEED_Pos             8
#define SFC_CMD_CMD_SPEED_Msk             BITS(8,9)
#define SFC_CMD_DATA_PHASE_Pos            7
#define SFC_CMD_DATA_PHASE_Msk            BIT(7)
#define SFC_CMD_DUMMY_PHASE_Pos           6
#define SFC_CMD_DUMMY_PHASE_Msk           BIT(6)
#define SFC_CMD_ADDR_PHASE_Pos            5
#define SFC_CMD_ADDR_PHASE_Msk            BIT(5)
#define SFC_CMD_CMD_PHASE_Pos             4
#define SFC_CMD_CMD_PHASE_Msk             BIT(4)
#define SFC_CMD_DATA_DIR_Pos              2
#define SFC_CMD_DATA_DIR_Msk              BITS(2,3)
#define SFC_CMD_XTS_BYPASS_Pos            1
#define SFC_CMD_XTS_BYPASS_Msk            BIT(1)
#define SFC_CMD_CMD_FINAL_Pos             0
#define SFC_CMD_CMD_FINAL_Msk             BIT(0)


#define SFC_CMD_ADDR_Pos                  0
#define SFC_CMD_ADDR_Msk                  BITS(0,23)

#define SFC_CTRL_FRAME_BITS_Pos           24
#define SFC_CTRL_FRAME_BITS_Msk           BITS(24,31)
#define SFC_CTRL_SPI_WPN_Pos              5
#define SFC_CTRL_SPI_WPN_Msk              BIT(5)
#define SFC_CTRL_SPI_HOLDN_Pos            4
#define SFC_CTRL_SPI_HOLDN_Msk            BIT(4)
#define SFC_CTRL_RX_FIFO_CLR_Pos          3
#define SFC_CTRL_RX_FIFO_CLR_Msk          BIT(3)
#define SFC_CTRL_TX_FIFO_CLR_Pos          2
#define SFC_CTRL_TX_FIFO_CLR_Msk          BIT(2)
#define SFC_CTRL_CMD_TYPE_Pos             1
#define SFC_CTRL_CMD_TYPE_Msk             BIT(1)
#define SFC_CTRL_CMD_START_Pos            0
#define SFC_CTRL_CMD_START_Msk            BIT(0)

#define SFC_STAT_FRAME_BITS_Max_Pos       24
#define SFC_STAT_FRAME_BITS_Max_Msk       BITS(24, 31)
#define SFC_STAT_RX_FIFO_WORDS_Pos        12
#define SFC_STAT_RX_FIFO_WORDS_Msk        BITS(12, 15)
#define SFC_STAT_TX_FIFO_WORDS_Pos        8
#define SFC_STAT_TX_FIFO_WORDS_Msk        BITS(8,11)
#define SFC_STAT_RX_FIFO_FULL_Pos         3
#define SFC_STAT_RX_FIFO_FULL_Msk         BIT(3)
#define SFC_STAT_TX_FIFO_EMPTY_Pos        2
#define SFC_STAT_TX_FIFO_EMPTY_Msk        BIT(2)
#define SFC_STAT_CMD_BUSY_Pos             0
#define SFC_STAT_CMD_BUSY_Msk             BIT(0)

#define SFC_IE_RX_FIFO_FULL_Pos           3
#define SFC_IE_RX_FIFO_FULL_Msk           BIT(3)
#define SFC_IE_TX_FIFO_EMPTY_Pos          2
#define SFC_IE_TX_FIFO_EMPTY_Msk          BIT(2)
#define SFC_IE_CMD_DONE_Pos               0
#define SFC_IE_CMD_DONE_Msk               BIT(0)

#define SFC_IF_RX_FIFO_FULL_Pos           3
#define SFC_IF_RX_FIFO_FULL_Msk           BIT(3)
#define SFC_IF_TX_FIFO_EMPTY_Pos          2
#define SFC_IF_TX_FIFO_EMPTY_Msk          BIT(2)
#define SFC_IF_CMD_DONE_Pos               0
#define SFC_IF_CMD_DONE_Msk               BIT(0)

#define SFC_FLOW_CFG_FLASH_CMD_Pos        24
#define SFC_FLOW_CFG_FLASH_CMD_Msk        BITS(24,31)
#define SFC_FLOW_CFG_DUMMY_BYTES_Pos      20
#define SFC_FLOW_CFG_DUMMY_BYTES_Msk      BITS(20,23)
#define SFC_FLOW_CFG_ADDR_BYTES_Pos       16
#define SFC_FLOW_CFG_ADDR_BYTES_Msk       BITS(16,19)
#define SFC_FLOW_CFG_DATA_SPEED_Pos       14
#define SFC_FLOW_CFG_DATA_SPEED_Msk       BITS(14,15)
#define SFC_FLOW_CFG_DUMMY_SPEED_Pos      12
#define SFC_FLOW_CFG_DUMMY_SPEED_Msk      BITS(12,13)
#define SFC_FLOW_CFG_ADDR_SPEED_Pos       10
#define SFC_FLOW_CFG_ADDR_SPEED_Msk       BITS(10,11)
#define SFC_FLOW_CFG_CMD_SPEED_Pos        8
#define SFC_FLOW_CFG_CMD_SPEED_Msk        BITS(8,9)
#define SFC_FLOW_CFG_XTS_BYPASS_Pos       1
#define SFC_FLOW_CFG_XTS_BYPASS_Msk       BIT(1)

#define SFC_XTS_TW_KEY_WR_WORDS_Pos       12
#define SFC_XTS_TW_KEY_WR_WORDS_Msk       BITS(12,15)
#define SFC_XTS_TX_KEY_WR_WORDS_Pos       8
#define SFC_XTS_TX_KEY_WR_WORDS_Msk       BITS(8,11)
#define SFC_XTS_TW_KEY_CLR_Pos            5
#define SFC_XTS_TW_KEY_CLR_Msk            BIT(5)
#define SFC_XTS_TX_KEY_CLR_Pos            4
#define SFC_XTS_TX_KEY_CLR_Msk            BITS(4)
#define SFC_XTS_KEY_LEN_Pos               3
#define SFC_XTS_KEY_LEN_Msk               BITS(3)
#define SFC_XTS_KEY_LD_FAIL_Pos           2
#define SFC_XTS_KEY_LD_FAIL_Msk           BITS(2)
#define SFC_XTS_KEY_LD_DONE_Pos           1
#define SFC_XTS_KEY_LD_DONE_Msk           BITS(1)
#define SFC_XTS_KEY_LD_Pos                0
#define SFC_XTS_KEY_LD_Msk                BITS(0)

typedef struct {
    uint32_t spi_pol_pha;                                                       /*!< SPI CPOL and CPHA */
    uint32_t csn_lead_time;                                                     /*!< Indicates the number of half sck cycles between the falling edge of csn and the first edge of sck */
    uint32_t csn_tail_time;                                                     /*!< Indicates the number of half sck cycles between the last edge of sck and raising edge of csn*/
    uint32_t csn_idle_time;                                                     /*!< Indicates the number of half sck cycles between commands*/
    uint32_t clk_div;                                                           /*!< sck clock divide factor */
    uint32_t byte_order;
} sfc_cfg_struct;

typedef struct {
	uint32_t cmd;
	uint32_t dummy_bytes;
	uint32_t addr_bytes;
	uint32_t data_speed;
	uint32_t dummy_speed;
	uint32_t addr_speed;
	uint32_t cmd_speed;
	uint32_t data_phase;
	uint32_t dummy_phase;
	uint32_t addr_phase;
	uint32_t cmd_phase;
	uint32_t data_dir;
} sfc_cmd_struct;

#define SFC_SPEED_SPI   0x0
#define SFC_SPEED_DPI   0x1
#define SFC_SPEED_QPI   0x2

#define SFC_DIR_DUMMY   0x0
#define SFC_DIR_RX_ONLY 0x1
#define SFC_DIR_TX_ONLY 0x2
#define SFC_DIR_TX_RX   0x3

#define SFC_BYTE_ORDER_LE 0x0
#define SFC_BYTE_ORDER_BE 0x1

/* function declarations */
/* reset SFC */
void sfc_deinit();
void sfc_init(sfc_cfg_struct *cfg);
void sfc_cmd_init(sfc_cmd_struct *cmd);
void sfc_flash_cmd_only();
void sfc_flash_erase(uint32_t addr);
void sfc_flash_rd_reg(uint8_t *data);
void sfc_flash_wr_reg(uint8_t *data);
ErrStatus sfc_flash_rd(uint32_t xts_bypass, uint32_t addr, uint32_t data_bits, uint8_t* data);
ErrStatus sfc_flash_pg(uint32_t xts_bypass, uint32_t addr, uint32_t data_bits, uint8_t* data);
void sfc_spi_wpn_actived();
void sfc_spi_wpn_inactived();
void sfc_spi_holdn_actived();
void sfc_spi_holdn_inactived();


LINK32FA016BX_END_DECLS

#endif /* LINK32FA016BX_SFC_H */
